﻿// opengl_glut_glew_imgui.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "glm/glm.hpp"
#include "GL/glew.h"
#include "GL/freeglut.h"


//imgui
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_glut.h"
#include "imgui_impl_opengl3.h"

#include "wdirtools.h"
#include "wstringutils.h"
#include "Shader.h"


void ResizeFunction(int, int);
void RenderFunction(void);
void InitWindow(int xpos, int ypos, int width, int height);

int g_windowWidth = 800;
int g_windowHeight = 600;
Shader* g_shader = nullptr;
GLuint g_vao = 0;//this is vertex buffer array object
GLuint g_buffer_vertex = 0;
GLuint g_buffer_index = 0;

float vertices[] = {
    -1.0f,  1.0f, 0.0f, 
    -1.0f, -1.0f, 0.0f, 
     1.0f, -1.0f, 0.0f, 
     1.0f,  1.0f, 0.0f
};

unsigned short indices[] = {
    0 , 1 , 2,
    0,  2,  3 
};

int main()
{
    InitWindow(100 ,100 , g_windowWidth, g_windowHeight);

    Shader shader("demo-vert.js", "demo-frag.js");
    g_shader = &shader;
    //init demo triangle
    glGenBuffers(1, &g_buffer_vertex);
    glGenBuffers(1, &g_buffer_index);

    glBindBuffer(GL_ARRAY_BUFFER, g_buffer_vertex);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffer_index);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glGenVertexArrays(1, &g_vao);
    glBindVertexArray(g_vao);
    glBindBuffer(GL_ARRAY_BUFFER, g_buffer_vertex);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffer_index);
    glEnableVertexAttribArray(0);
    glBindVertexArray(0);



    glutMainLoop();

    //imgui shutdown
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGLUT_Shutdown();
    ImGui::DestroyContext();

    exit(EXIT_SUCCESS);
}



void InitWindow(int xpos, int ypos, int width, int height)
{
    int   no_use_argc = 1;
    char* no_use_argv[1];

    glutInit(&no_use_argc, no_use_argv);
    glutInitContextVersion(4, 0);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutSetOption(
        GLUT_ACTION_ON_WINDOW_CLOSE,
        GLUT_ACTION_GLUTMAINLOOP_RETURNS
    );
    glutInitWindowSize(width, height);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    int WindowHandle = glutCreateWindow("GLUT");
    if (WindowHandle < 1) {
        fprintf(
            stderr,
            "ERROR: Could not create a new rendering window.\n"
        );
        exit(EXIT_FAILURE);
    }

    glutReshapeFunc(ResizeFunction);
    glutDisplayFunc(RenderFunction);

    glewInit();//!!!important

    //imgui initialize
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    ImGui_ImplGLUT_Init();
    ImGui_ImplOpenGL3_Init();
    ImGui_ImplGLUT_InstallFuncs();
}


void ResizeFunction(int Width, int Height)
{
    glViewport(0, 0, Width, Height);
}


void RenderFunction(void)
{
    //imgui gui setup.
    {
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGLUT_NewFrame();
        ImGui::NewFrame();
        ImGuiIO& io = ImGui::GetIO();
        bool bval = false;
        ImGui::Checkbox("Use bool", &bval);
        float somefval = 50;
        ImGui::SliderFloat("wind speed", &somefval, 0.0f, 100.f);
        ImGui::Render();
    }
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // your render codes
    g_shader->use();
    // now render the triangle
    glEnableVertexAttribArray(g_vao);
    glBindVertexArray(g_vao);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);

    glUseProgram(0);

    //imgui draw calls
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

    glutSwapBuffers();
    glutPostRedisplay();
}